#define RCC_APB2ENR (0x40021000 + 0x18)

#define IOPAEN 2
#define IOPBEN 3
#define GPIOA_CRL (0x40010800 + 0)
#define GPIOA_BSRR (0x40010800 + 0x10)
#define GPIOB_CRH (0x40010C00 + 4)
#define PA_BASE (0x40010800)
#define PB_BASE (0x40010C00)
#define GPIO_A_ODR (PA_BASE + 0x0C)
#define GPIO_B_ODR (PB_BASE + 0x0C)

#define PB13 (0x42000000+(GPIO_B_ODR - 0x40000000)*32 + 13*4)
#define PB14 (0x42000000+(GPIO_B_ODR - 0x40000000)*32 + 14*4)
#define PB15 (0x42000000+(GPIO_B_ODR - 0x40000000)*32 + 15*4)

#define RED 0
#define BLUE 1
#define GREEN 2
#define FULL 3


#define GPIOC_CRH (0x40011000 + 4)
#define PC_BASE (0x40011000)
#define GPIO_C_ODR (PC_BASE + 0xc)
#define LED_PC13 (0x42000000+(GPIO_C_ODR - 0x40000000)*32 + 13*4)

extern void LED_Init(void);
extern void LED_ON(void);
extern void LED_OFF(void);
extern void Delay(void);

void led_init()
{
	unsigned int *pa = (unsigned int *)RCC_APB2ENR;
	unsigned int tempa = *pa;
	unsigned int *pb = (unsigned int *)RCC_APB2ENR;
	unsigned int tempb = *pb;
	
	tempa |= 3 << IOPAEN;
	*pa = tempa;
	
	pa = (unsigned int *)GPIOA_CRL;
	tempa = *pa;
	tempa = 0;
	tempa = 0x33333333;
	*pa = tempa;
	

	pb = (unsigned int *)GPIOB_CRH;
	tempb = *pb;
	tempb &= ~(0xFFF << 20);
	tempb |= 0x333 << 20;
	*pb = tempb;
}


void delay(int s)
{
	while(s--)
	{
		int i = 1000;
		while(i--);
	}
}

void switch_color(unsigned int flag, unsigned int rgb)
{
	volatile unsigned int *pb13 = (volatile unsigned int *)PB13; 
	volatile unsigned int *pb14 = (volatile unsigned int *)PB14;
	volatile unsigned int *pb15 = (volatile unsigned int *)PB15;
	if(flag == 0)
	{
		switch(rgb)
		{
			case RED :
			{				
				*pb13 = 0;
				*pb14 = 1;
				*pb15 = 1;
				break;
			}
			case GREEN :
			{
				*pb13 = 1;
				*pb14 = 0;
				*pb15 = 1;
				break;
			}
			case BLUE :
			{
				*pb13 = 1;
				*pb14 = 1;
				*pb15 = 0;
				break;
			}
			case FULL :
			{
				*pb13 = 0;
				*pb14 = 0;
				*pb15 = 0;
				break;
			}
		}
	}
	else
	{
		*pb13 = 1;
		*pb14 = 1;
		*pb15 = 1;
	}
}


void led_on(unsigned int i, unsigned int flag, unsigned int rgb)
{
	volatile unsigned int *p = (volatile unsigned int *)(0x42000000+(GPIO_A_ODR - 0x40000000)*32 + i * 4);
	*p = 0;
	switch_color(0, rgb);
}

void led_off(unsigned int i, unsigned int flag, unsigned int rgb)
{
	volatile unsigned int *p = (volatile unsigned int *)(0x42000000+(GPIO_A_ODR - 0x40000000)*32 + i * 4);
	*p = 1;
	switch_color(0, rgb);
}


void __main(void)
{
	unsigned int i = 0;
	unsigned int j = 0;
	led_init();
	
	while(1)
	{	
		for(i = 0, j = 7; i < j; i++, j--)
		{
			led_on(i, 0, FULL);
			delay(1000);
			led_off(i, 1, GREEN);
			led_on(j, 0, FULL);
			delay(1000);
			led_off(j, 1, GREEN);
		}
		
		for(i = 0; i < 8; i++)
		{
			led_on(i, 0, RED);
			delay(300);
			led_off(i, 1, RED);
			delay(300);
		}
		
		i = 7;

		while(i--)
		{
			led_on(i, 0, GREEN);
			delay(300);
			led_off(i, 1, GREEN);
			delay(300);
		}
		
		for(i = 3, j = 4; i < 0, j < 8; i--, j++)
		{
			led_on(i, 0, BLUE);
			led_on(j, 0, RED);
			delay(1000);
			led_off(i, 1, BLUE);
			led_off(j, 1, RED);
			delay(1000);
		}
		
		for(i = 0, j = 7; i < j; i++, j--)
		{
			led_on(i, 0, RED);
			led_on(j, 0, FULL);
			delay(1000);
			led_off(i, 1, RED);
			led_off(j, 1, FULL);
			delay(1000);
		}
		
		for(i = 3, j = 4; i < 0, j < 8; i--, j++)
		{
			led_on(i, 0, GREEN);
			delay(300);
			led_off(i, 1, GREEN);
			led_on(j, 0, BLUE);
			delay(300);
			led_off(j, 1, BLUE);
		}
		
		for(i = 0; i < 8; i++)
		{
			led_on(i, 0, RED);
			delay(300);
			led_off(i, 1, RED);
			delay(300);
		}
		

		for(i = 0, j = 7; i < j; i++, j--)
		{
			led_on(i, 0, GREEN);
			delay(200);
			led_off(i, 1, GREEN);
			led_on(j, 0, BLUE);
			delay(200);
			led_off(j, 1, BLUE);
		}
	}	
}
